final class Archive {
	public Archive(byte data[]) {
		Packet stream = new Packet(data);
		int decompressedSize = stream.get24BitInt();
		int compressedSize = stream.get24BitInt();
		if (compressedSize != decompressedSize) {
			byte abyte1[] = new byte[decompressedSize];
			BZip2Decompressor.decompressBuffer(abyte1, decompressedSize, data, compressedSize, 6);
			finalBuffer = abyte1;
			stream = new Packet(finalBuffer);
			compressedAsWhole = true;
		} else {
			finalBuffer = data;
			compressedAsWhole = false;
		}
		totalFiles = stream.getUnsignedShort();
		identifiers = new int[totalFiles];
		decompressedSizes = new int[totalFiles];
		compressedSizes = new int[totalFiles];
		startOffsets = new int[totalFiles];
		int offset = stream.offset + totalFiles * 10; //file info at beginning is 10 bytes per file, and we want to start file data immediately after
		for (int l = 0; l < totalFiles; l++) {
			identifiers[l] = stream.getInt(); //  4
			decompressedSizes[l] = stream.get24BitInt();//  3
			compressedSizes[l] = stream.get24BitInt(); //+ 3
			startOffsets[l] = offset; //____
			offset += compressedSizes[l]; // 10
		}
	}

	public byte[] getFile(int identifier) {
		byte dataBuffer[] = null;
		for (int k = 0; k < totalFiles; k++) {
			if (identifiers[k] == identifier) {
				if (dataBuffer == null) {
					dataBuffer = new byte[decompressedSizes[k]];
				}
				if (!compressedAsWhole) {
					BZip2Decompressor.decompressBuffer(dataBuffer, decompressedSizes[k],
					finalBuffer, compressedSizes[k], startOffsets[k]);
				} else {
					System.arraycopy(finalBuffer, startOffsets[k], dataBuffer, 0,
					decompressedSizes[k]);
				}
				return dataBuffer;
			}
		}
		return null;
	}

	public byte[] getFile(String identStr) {
		byte dataBuffer[] = null;
		int identifier = 0;
		identStr = identStr.toUpperCase();
		for (int j = 0; j < identStr.length(); j++) {
			identifier = (identifier * 61 + identStr.charAt(j)) - 32;
		}
		for (int k = 0; k < totalFiles; k++) {
			if (identifiers[k] == identifier) {
				if (dataBuffer == null) {
					dataBuffer = new byte[decompressedSizes[k]];
				}
				if (!compressedAsWhole) {
					BZip2Decompressor.decompressBuffer(dataBuffer, decompressedSizes[k],
					finalBuffer, compressedSizes[k], startOffsets[k]);
				} else {
					System.arraycopy(finalBuffer, startOffsets[k], dataBuffer, 0,
					decompressedSizes[k]);
				}
				return dataBuffer;
			}
		}
		return null;
	}

	final byte[] finalBuffer;
	final int totalFiles;
	final int[] identifiers;
	final int[] decompressedSizes;
	final int[] compressedSizes;
	final int[] startOffsets;
	final boolean compressedAsWhole;
}